package www.wen.com.common.lib.di.api


import com.google.gson.Gson
import com.google.gson.JsonParser
import com.google.gson.JsonPrimitive
import com.hjq.toast.ToastUtils
import com.orhanobut.logger.Logger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import www.wen.com.common.lib.data.entities.builtIn.LazyEntity
import www.wen.com.common.lib.data.entities.builtIn.LazyPageEntity
import www.wen.com.common.lib.data.entities.builtIn.Page
import www.wen.com.common.lib.data.entities.builtIn.Result
import www.wen.com.common.lib.util.RESPONSE_SUCCESS_CODE
import java.io.IOException

/**
 * Created by luyao
 * on 2019/4/10 9:41
 */


suspend fun <T> apiCall(call: suspend () -> LazyEntity<T>): LazyEntity<T> {
    return call.invoke()
}

suspend fun <T> safeApiCall(call: suspend () -> Result<T>, errorMessage: String): Result<T> {
    return try {
        call()
    } catch (e: Exception) {
        // An exception was thrown when calling the API so we're converting this to an IOException
        Logger.i("Exception = ${e.message}")
        if (e.message?.contains("Failed to connect") == true) {
            ToastUtils.show("网络异常，请检查您的网络连接。")
        } else if (e.message?.contains("timeout") == true) {
            ToastUtils.show("网络请求超时，请检查您的网络连接。")
        }
        Result.Error(IOException(errorMessage, e))
    }
}

suspend fun <T> executeResponse(
    response: LazyEntity<T>,
    successBlock: (suspend CoroutineScope.() -> Unit)? = null,
    errorBlock: (suspend CoroutineScope.() -> Unit)? = null
): Result<T> {
    return coroutineScope {
        if (response.code != RESPONSE_SUCCESS_CODE) {
            errorBlock?.let { it() }
            Logger.i("Exception = ${response.msg}")
            Result.Error(IOException(response.msg))
        } else {
            successBlock?.let { it() }
            Result.Success(response.data)
        }
    }
}

suspend fun <T> executePageResponse(
    response: LazyPageEntity<T>,
    successBlock: (suspend CoroutineScope.() -> Unit)? = null,
    errorBlock: (suspend CoroutineScope.() -> Unit)? = null
): Result<Page<T>> {
    return coroutineScope {
        if (response.code != RESPONSE_SUCCESS_CODE) {
            errorBlock?.let { it() }
            Logger.i("Exception = ${response.message}")
            Result.Error(IOException(response.message))
        } else {
            successBlock?.let { it() }
            Result.Success(response.data)
        }
    }
}

//suspend fun <T : Any> executeResponse(
//    success: Class<T>,
//    response: String,
//    successBlock: (suspend CoroutineScope.() -> Unit)? = null,
//    errorBlock: (suspend CoroutineScope.() -> Unit)? = null
//): Result<T> {
//    return coroutineScope {
//        Logger.i("数据打印  = $response")
//        val code: JsonObject? = JsonParser.parseString(response).asJsonObject.getAsJsonObject("errcode")
//        if (code != null) {
//            val errorEntity = Gson().fromJson(response, WeiXinErrcodeEntity::class.java)
//            errorBlock?.let { it() }
//            Result.Error(IOException(errorEntity.errmsg))
//        } else {
//            val wxEntity: T = Gson().fromJson(response, success)
//            successBlock?.let { it() }
//            Result.Success(wxEntity)
//        }
//    }
//
//}

//qq - 成功为0,关键字段 ret
suspend fun <T : Any, E : Any> executeResponse(
    success: Class<T>,
    error: Class<E>,
    response: String,
    verdictField: String,
    successCode: Int,
    errorBlock: ((E) -> Result.Error)? = null,
    successBlock: ((T) -> Result.Success<T>)? = null
): Result<T>? {
    return coroutineScope {


        JsonParser().parse(response).asJsonObject.entrySet().forEach {
            val pid = it.value.asJsonObject.get("pid").asString
        }

        val code: JsonPrimitive? =
            JsonParser().parse(response).asJsonObject.getAsJsonPrimitive(verdictField)
        if (code != null) {
            val codeInt = code.asInt
            if (codeInt == successCode) {
                val successEntity = Gson().fromJson(response, success)
                successBlock?.invoke(successEntity as T)
            } else {
                val errorEntity = Gson().fromJson(response, error)
                errorBlock?.invoke(errorEntity as E)
            }
        } else {
            Result.Error(IllegalArgumentException("verdictField关键字段缺失"))
        }
    }
}



